/**
 *
 */
package pers.vic.test.http;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;


/**
 *  @description: 替换request ,保证request的body可重复读的过滤器
 *  @author Vic.xu
 *  @date: 2020年5月20日上午9:07:14
 */
public class ReplaceHttpRequest4RepeatReadBodyFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 是否拦截
        if (!judgeFilter(request)) {
            chain.doFilter(request, response);
            return;
        }

        // 重新包装流, 只包装JSON请求的
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest && isJsonRequest(request)) {
            requestWrapper = new RepeatReadServletRequestBodyWrapper((HttpServletRequest) request);
        }
        //获取请求中的流如何，将取出来的字符串，再次转换成流，然后把它放入到新request对象中。
        if (requestWrapper == null) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }

    private static final String FILTER_PREFIX = "";

    /**
     * 只拦截指定前缀的url
     * @param request
     * @return
     */
    private boolean judgeFilter(ServletRequest request) {
        String url = getRequestUrl((HttpServletRequest) request);
        return url.startsWith(FILTER_PREFIX);
    }

    /**
     * 获得当前请求的URL
     * 不是用request.getServletPath() 是因为这个API和URL-MAPPING有变化关系
     */
    public static String getRequestUrl(HttpServletRequest request) {
        String contextPath = request.getContextPath();
        String requestUri = request.getRequestURI();
        int i = requestUri.indexOf("?");
        if (i < 0) {
            i = requestUri.length();
        }
        return requestUri.substring(contextPath.length(), i);
    }

    /**
     * 是否是JSON请求格式
     * @param request
     * @return
     */
    public static boolean isJsonRequest(ServletRequest request) {
        String enctype = request.getContentType();
        return StringUtils.isNotBlank(enctype) && enctype.contains(MediaType.APPLICATION_JSON_VALUE);
    }


}
